package pl.edu.agh.io.fx3.monitor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import pl.edu.agh.io.fx3.exceptions.FileAlreadyExistsException;

/**
 * Interface which makes up an abstract representation of file and directory
 * pathnames. It is a wrapper to java.io.File implementation.
 * 
 * @author Jaroslaw Janik
 */
public interface IFile {

	/**
	 * Tests whether the application can read the file denoted by this abstract
	 * vfs pathname.
	 * 
	 * @return True if and only if the file specified by this abstract vfs
	 *         pathname exists and can be read by the application; false
	 *         otherwise.
	 */
	public boolean canRead();

	/**
	 * Tests whether the application can modify to the file denoted by this
	 * abstract vfs pathname.
	 * 
	 * @return True if and only if the file system actually contains a file
	 *         denoted by this abstract vfs pathname and the application is
	 *         allowed to write to the file; false otherwise.
	 */
	public boolean canWrite();

	/**
	 * Atomically creates a new, empty file named by this abstract vfs pathname
	 * if and only if a file with this name does not yet exist
	 * 
	 * @return True if the named file does not exist and was successfully
	 *         created; false if the named file already exists.
	 * @throws IOException
	 */
	public boolean createNewFile() throws IOException, FileAlreadyExistsException;

	/**
	 * Deletes the file or directory denoted by this abstract vfs pathname.
	 * 
	 * @return True if and only if the file or directory is successfully
	 *         deleted; false otherwise.
	 */
	public boolean delete();

	/**
	 * Returns instance of FileInputStream which is linked with specific IFile.
	 * Thanks to it, it can be used to read something from file in easy way.
	 * 
	 * @return New instance of FileInputStream linked to file. Null if file does
	 *         not exists.
	 * @throws FileNotFoundException
	 */
	public FileInputStream getFileInputStream() throws FileNotFoundException;

	/**
	 * Returns instance of FileOutputStream which is linked with specific IFile.
	 * Thanks to it, it can be used to write something to file in easy way. If
	 * file does not exist, it will be created.
	 * 
	 * @return New instance of FileOutputStream linked to file, null if file
	 *         cannot be created.
	 * @throws IOException
	 * @throws FileNotFoundException
	 * @throws FileAlreadyExistsException
	 */
	public FileOutputStream getFileOutputStream() throws FileNotFoundException,
			IOException, FileAlreadyExistsException;

	/**
	 * Returns instance of FileReader which is linked with specific IFile.
	 * Thanks to it, it can be used to read something from file in easy way.
	 * Null if file does not exists.
	 * 
	 * @return New instance of FileReader linked to file.
	 * @throws IOException
	 */
	public FileReader getFileReader() throws IOException;
	
	/**
	 * Returns instance of FileWriter which is linked with specific IFile.
	 * Thanks to it, it can be used to write something to file in easy way. If
	 * file does not exist, it will be created.
	 * 
	 * @return New instance of FileWriter linked to file, null if file cannot be
	 *         created.
	 * @throws IOException
	 * @throws FileAlreadyExistsException
	 */
	public FileWriter getFileWriter() throws IOException,
			FileAlreadyExistsException;

	/**
	 * Returns the name of the file or directory denoted by this abstract vfs
	 * pathname.
	 * 
	 * @return The name of the file or directory denoted by this abstract vfs
	 *         pathname, or the empty string if this pathname's name sequence is
	 *         empty.
	 */
	public String getName();

	/**
	 * Converts this abstract pathname into a vfs pathname string.
	 * 
	 * @return The string form of vfs pathname.
	 */
	public String getPath();

	/**
	 * Returns parent IFile.
	 * 
	 * @return The abstract vfs pathname of the parent directory named by this
	 *         abstract vfs pathname, or null if this pathname does not name a
	 *         parent.
	 */
	public IFile getParentFile();

	/**
	 * Converts this abstract real pathname into a pathname string.
	 * 
	 * @return The string form of this abstract real pathname. Null if file does
	 *         not exist.
	 */
	public String getRealPath();

	/**
	 * Checks whether file is related to directory.
	 * 
	 * @return True if file exists and is a directory; false otherwise.
	 */
	public boolean isDirectory();

	/**
	 * Checks whether file is related to a normal file.
	 * 
	 * @return True if file exists and is a normal file; false otherwise.
	 */
	public boolean isFile();

	/**
	 * Checks whether file is a hidden file. The exact definition of hidden is
	 * system-dependent.
	 * 
	 * @return True if file is a hidden file; false otherwise.
	 */
	public boolean isHidden();

	/**
	 * Returns the length of the file denoted by IFile.
	 * 
	 * @return The length, in bytes, of the file denoted by this abstract
	 *         pathname, or 0L if the file does not exist. The return value is
	 *         unspecified if this pathname denotes a directory.
	 */
	public long length();

	/**
	 * Returns an array of IFiles in the directory.
	 * 
	 * @return An array of IFiles when is there any. The array will be empty if
	 *         the directory is empty. Return null if IFile does not denote a
	 *         directory.
	 */
	public IFile[] listFiles();

	/**
	 * Creates the directory named by this abstract vfs pathname.
	 * 
	 * @return True if and only if the directory was created; false otherwise.
	 */
	public boolean mkdir();

	/**
	 * Renames the file
	 * 
	 * @param file
	 *            The new pathname for the named file.
	 * @return True if and only if the renaming succeeded; false otherwise.
	 * @throws NullPointerException
	 *             If file parameter is null.
	 */
	public boolean renameTo(IFile file) throws NullPointerException;
}